package com.example.rabc.service.impl;

import com.example.rabc.dao.PermissionRepository;
import com.example.rabc.dao.UserRepository;
import com.example.rabc.exception.BusinessException;
import com.example.rabc.entity.Permission;
import com.example.rabc.entity.User;
import com.example.rabc.monitor.Monitored;
import com.example.rabc.service.PermissionService;
import com.example.rabc.service.PermissionComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 权限服务实现类
 */
@Service
@Transactional
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    private PermissionRepository permissionRepository;

    @Autowired
    private UserRepository userRepository;

    /**
     * 创建权限
     * @param permission 权限实体
     * @return 创建的权限实体
     */
    @Override
    @Monitored
    public Permission createPermission(Permission permission) {
        // 检查权限代码是否已存在
        if (permissionRepository.findByPermissionCode(permission.getPermissionCode()).isPresent()) {
            throw new BusinessException("权限代码已存在");
        }

        return permissionRepository.save(permission);
    }

    /**
     * 更新权限
     * @param permissionId 权限ID
     * @param permission 权限实体
     * @return 更新后的权限实体
     */
    @Override
    @Monitored
    public Permission updatePermission(Long permissionId, Permission permission) {
        Permission existingPermission = permissionRepository.findById(permissionId)
                .orElseThrow(() -> new BusinessException("权限不存在"));

        // 检查权限代码是否被其他权限使用
        if (!existingPermission.getPermissionCode().equals(permission.getPermissionCode())) {
            if (permissionRepository.findByPermissionCode(permission.getPermissionCode()).isPresent()) {
                throw new BusinessException("权限代码已存在");
            }
        }

        // 更新权限信息
        existingPermission.setPermissionName(permission.getPermissionName()); // 更新权限名称
        existingPermission.setPermissionCode(permission.getPermissionCode()); // 更新权限编码
        existingPermission.setResourceType(permission.getResourceType()); // 更新资源类型
        existingPermission.setResourcePath(permission.getResourcePath()); // 更新资源路径
        existingPermission.setParentId(permission.getParentId()); // 更新父权限ID
        existingPermission.setDescription(permission.getDescription()); // 更新权限描述
        existingPermission.setStatus(permission.getStatus()); // 更新状态

        return permissionRepository.save(existingPermission);
    }

    /**
     * 删除权限
     * @param permissionId 权限ID
     */
    @Override
    @Monitored
    public void deletePermission(Long permissionId) {
        if (!permissionRepository.existsById(permissionId)) {
            throw new BusinessException("权限不存在");
        }
        permissionRepository.deleteById(permissionId);
    }

    /**
     * 根据ID获取权限
     * @param permissionId 权限ID
     * @return 权限实体
     */
    @Override
    @Monitored
    @Transactional(readOnly = true)
    public Permission getPermissionById(Long permissionId) {
        return permissionRepository.findById(permissionId)
                .orElseThrow(() -> new BusinessException("权限不存在"));
    }

    /**
     * 根据权限编码获取权限
     * @param permissionCode 权限编码
     * @return 权限实体
     */
    @Override
    @Monitored
    @Transactional(readOnly = true)
    public Permission getPermissionByCode(String permissionCode) {
        return permissionRepository.findByPermissionCode(permissionCode)
                .orElseThrow(() -> new BusinessException("权限不存在"));
    }

    /**
     * 获取所有权限
     * @return 权限实体列表
     */
    @Override
    @Monitored
    @Transactional(readOnly = true)
    public List<Permission> getAllPermissions() {
        return permissionRepository.findAll();
    }

    /**
     * 根据资源类型获取权限
     * @param resourceType 资源类型
     * @return 权限实体列表
     */
    @Override
    @Monitored
    @Transactional(readOnly = true)
    public List<Permission> getPermissionsByResourceType(String resourceType) {
        return permissionRepository.findByResourceType(resourceType);
    }

    /**
     * 获取权限树结构
     * @param rootPermissionId 根权限ID，如果为null则构建整棵树
     * @return 权限树根节点
     */
    @Override
    @Monitored
    @Transactional(readOnly = true)
    public PermissionComponent getPermissionTree(Long rootPermissionId) {
        List<Permission> allPermissions = permissionRepository.findAll();

        if (allPermissions.isEmpty()) {
            return null;
        }

        if (rootPermissionId == null) {
            // 构建整棵树，从根节点开始（parentId为0的节点）
            List<Permission> rootPermissions = allPermissions.stream()
                    .filter(p -> p.getParentId() == null || p.getParentId() == 0)
                    .collect(Collectors.toList());

            if (rootPermissions.isEmpty()) {
                return null;
            }

            // 创建一个虚拟的根节点来包含所有根权限
            Permission virtualRoot = new Permission();
            virtualRoot.setId(0L);
            virtualRoot.setPermissionName("权限树根节点");
            virtualRoot.setPermissionCode("ROOT");
            virtualRoot.setParentId(null);

            CompositePermission root = new CompositePermission(virtualRoot);

            // 为每个根权限创建节点并添加到虚拟根节点中
            for (Permission rootPermission : rootPermissions) {
                boolean hasChildren = allPermissions.stream()
                        .anyMatch(p -> p.getParentId() != null && p.getParentId().equals(rootPermission.getId()));

                if (hasChildren) {
                    CompositePermission childNode = new CompositePermission(rootPermission);
                    root.add(childNode);
                    buildSubtree(childNode, allPermissions);
                } else {
                    LeafPermission leafNode = new LeafPermission(rootPermission);
                    root.add(leafNode);
                }
            }

            return root;
        } else {
            // 构建以指定节点为根的子树
            return CompositePermission.buildPermissionTree(allPermissions, rootPermissionId);
        }
    }

    /**
     * 递归构建子树
     * @param parent 父节点
     * @param allPermissions 所有权限列表
     */
    @Monitored
    private void buildSubtree(CompositePermission parent, List<Permission> allPermissions) {
        Long parentId = parent.getId();

        // 查找所有父ID为parentId的权限
        List<Permission> children = allPermissions.stream()
                .filter(p -> p.getParentId() != null && p.getParentId().equals(parentId))
                .collect(Collectors.toList());

        // 为每个子权限创建节点并添加到父节点中
        for (Permission childPermission : children) {
            // 判断是叶子节点还是复合节点
            boolean hasChildren = allPermissions.stream()
                    .anyMatch(p -> p.getParentId() != null && p.getParentId().equals(childPermission.getId()));

            if (hasChildren) {
                // 有子节点，创建复合节点
                CompositePermission childNode = new CompositePermission(childPermission);
                parent.add(childNode);
                // 递归构建子树
                buildSubtree(childNode, allPermissions);
            } else {
                // 没有子节点，创建叶子节点
                LeafPermission leafNode = new LeafPermission(childPermission);
                parent.add(leafNode);
            }
        }
    }

    /**
     * 检查用户是否具有指定权限（基于权限树）
     * @param userId 用户ID
     * @param permissionCode 权限代码
     * @return 是否具有权限
     */
    @Override
    @Monitored
    @Transactional(readOnly = true)
    public boolean checkUserPermission(Long userId, String permissionCode) {
        // 获取用户及其角色和权限
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException("用户不存在"));

        // 检查用户直接拥有的权限
        boolean hasDirectPermission = user.getRoles().stream()
                .flatMap(role -> role.getPermissions().stream())
                .anyMatch(permission -> permission.getPermissionCode().equals(permissionCode));

        if (hasDirectPermission) {
            return true;
        }

        // 构建权限树并检查继承权限
        PermissionComponent permissionTree = getPermissionTree(null);
        if (permissionTree != null) {
            return permissionTree.hasPermission(permissionCode);
        }

        return false;
    }

    /**
     * 获取用户权限树
     * @param userId 用户ID
     * @return 用户权限树
     */
    @Override
    @Monitored
    @Transactional(readOnly = true)
    public List<PermissionComponent> getUserPermissionTree(Long userId) {
        // 获取用户及其角色和权限
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException("用户不存在"));

        // 获取用户的所有权限
        List<Permission> userPermissions = user.getRoles().stream()
                .flatMap(role -> role.getPermissions().stream())
                .distinct()
                .collect(Collectors.toList());

        // 构建用户权限树
        return buildUserPermissionTree(userPermissions);
    }

    /**
     * 构建用户权限树
     * @param userPermissions 用户权限列表
     * @return 用户权限树
     */
    @Monitored
    private List<PermissionComponent> buildUserPermissionTree(List<Permission> userPermissions) {
        // 这里可以根据需要实现用户权限树的构建逻辑
        // 目前简单地将用户权限转换为权限组件
        return userPermissions.stream()
                .map(permission -> {
                    // 判断是叶子节点还是复合节点
                    // 这里简化处理，都作为叶子节点
                    return new LeafPermission(permission);
                })
                .collect(Collectors.toList());
    }
}